package com.gooluke.shorten.service.impl;

import com.gooluke.common.util.ExceptionUtil;
import com.gooluke.shorten.context.GenerateContext;
import com.gooluke.shorten.dao.ShortUrlDao;
import com.gooluke.shorten.entity.ShortUrl;
import com.gooluke.shorten.model.BatchDeleteRequest;
import com.gooluke.shorten.model.GenerateRequest;
import com.gooluke.shorten.model.RenewRequest;
import com.gooluke.shorten.model.UpdateShortUrlRequest;
import com.gooluke.shorten.model.vo.CreateShortUrlVO;
import com.gooluke.shorten.service.ShortUrlService;
import com.gooluke.shorten.strategy.ShortCodeStrategy;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

/**
 * @author gooluke
 * description
 * datetime 2025-03-29 14:16
 */
@Service
public class ShortUrlServiceImpl implements ShortUrlService {

    private static final int DEFAULT_RETRY_COUNT = 3;

    @Autowired
    private ShortCodeStrategy strategy;
    @Autowired
    private ShortUrlDao shortUrlDao;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CreateShortUrlVO createShortUrl(GenerateRequest request) {
        // 1. 安全检查
        //securityChecker.check(request.getOriginalUrl());

        // 2. 生成短码（自动重试3次）
        String shortCode = generateWithRetry(request);

        // 3. 存储映射关系
        ShortUrl entity = ShortUrl.builder()
                .shortCode(shortCode)
                .originalUrl(request.getOriginalUrl())
                .userId(request.getCreator())
                .expireTime(calculateExpireTime(request.getExpireTime()))
                .build();

        boolean result = shortUrlDao.save(entity);
        ExceptionUtil.isTrue(result, "创建短链接失败");
        CreateShortUrlVO shortUrlVO = new CreateShortUrlVO();
        BeanUtils.copyProperties(entity, shortUrlVO);
        return shortUrlVO;
    }

    @Override
    public void renewShortUrl(String code, RenewRequest request) {

    }

    @Override
    public void batchDelete(BatchDeleteRequest request) {

    }

    @Override
    public void updateShortUrl(UpdateShortUrlRequest request) {

    }

    @Override
    public void archiveShortUrl(String code) {

    }

    private LocalDateTime calculateExpireTime(Date expireTime) {
        return expireTime == null ? null : expireTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    private String generateWithRetry(GenerateRequest request) {
        return generateWithRetry(request, DEFAULT_RETRY_COUNT);
    }

    private String generateWithRetry(GenerateRequest request, int retryTimes) {
        int retry = 0;
        GenerateContext context = new GenerateContext(request.getCreator(), request.getCustomShortKey());

        while (retry++ < retryTimes) {
            String code = strategy.generate(request.getOriginalUrl(), context);
            if (!shortUrlDao.existsByShortCode(code)) {
                return code;
            }

            ExceptionUtil.isTrue(strategy.isCustom() && StringUtils.hasLength(context.getCustomShortKey()), "短码已被占用");

        }
        ExceptionUtil.throwDefaultException("短码生成冲突，请重试");
        return null;
    }

}
